package com.ce.framework.ant;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class UpdateCopy extends Task {

    private static Log log = LogFactory.getLog(UpdateCopy.class);
	
	private String updateTxtPath;
	private String toDir;
	private String webroot="webroot";
	private String webBase;
	private String webSrcDirs = "src";
	private String svnWebappUri = "0_csmis/source/";

	/**
	 * 开发人：andy
	 * 开发日期: 2013-11-14  下午05:44:51
	 * 功能描述: 
	 * 方法的参数和返回值: 
	 * @param args
	 */
	public static void main(String[] args) {
		UpdateCopy uc = new UpdateCopy();
		uc.updateTxtPath = "D:/ntax1.0/update.txt";//SVN提交后产生的日志内容所在文件路径
		uc.setToDir("D:/ntax1.0/update\\csmis");
		uc.setWebBase(new File(new File("1").getAbsolutePath()).getParent());
		uc.execute();
		//System.out.println(new File(new File("1").getAbsolutePath()).getParent());
	}

	@Override
	public void execute() throws BuildException {

		try {
			BufferedReader in = new BufferedReader(new FileReader(updateTxtPath));
			String line = in.readLine();
			String[] tmp = null;
			StringBuilder newFile = new StringBuilder();
			HashMap<String,String> hm = new HashMap<String,String>();
			String pre = null;
			int maxFilelen = 0;
			int allLine=0,lostLine = 0,repeatLine=0;
			while(line!=null){
				try {
					line = line.replace(":", "");//Commit Monitor的日志中会有: 去掉后与eclipse中的日志就一样了
					if(line.trim().length()==0){//不处理空白行
						continue;
					}
					allLine ++;
					tmp = line.trim().split("\\s+");
					if(tmp.length!=2){
						log.info("丢弃["+line+"]，原因:不能识别!");
						lostLine++;
						continue;
					}
					if("D".equals(tmp[0])||"Deleting".equals(tmp[0])){//删除的文件不做处理
						log.info("丢弃["+line+"]，原因:删除的文件!");
						lostLine++;
						continue;
					}
					String file = tmp[1];
					if(file.endsWith(".jsp")){//是JSP文件的不做处理
						log.info("丢弃["+line+"]，原因:本操作不处理JSP文件!");
						lostLine++;
						continue;
					}
					String srcPath = getWebPath(file);
					String distPath = getDistPath(file);
					maxFilelen = Math.max(maxFilelen, srcPath.length());
					if(!new File(srcPath).exists()){
						log.info("丢弃["+line+"]，原因:本地文件["+srcPath+"]不存在!");
						lostLine++;
						continue;
					}
					if(!new File(srcPath).isFile()){
						log.info("丢弃["+line+"]，原因:本地文件["+srcPath+"]指向了目录!");
						lostLine++;
						continue;
					}
					if(distPath==null){
						log.info("丢弃["+line+"]，原因:本地文件["+srcPath+"]不在webroot目录及可编译目录"+webSrcDirs+"下!");
						lostLine++;
						continue;
					}
					if(hm.get(srcPath)!=null)
						repeatLine++;
					hm.put(srcPath, distPath);
				} catch (Exception e) {
					log.error("文件["+updateTxtPath+"]解析时出现异常！",e);
				}
				finally{
					line = in.readLine();
				}
			}
			in.close();
			log.info("升级文件内共"+allLine+"行内容，其中重复"+repeatLine+"行，被丢弃"+lostLine+"行!");
			maxFilelen += 2;
			Iterator it = hm.keySet().iterator();
			while(it.hasNext()){
				String src = (String) it.next();
				String dist = hm.get(src);
				try {
					copyFile(src,dist);
					log.info("copying file "+addEnds(src,maxFilelen)+"to  "+dist);
				} catch (Exception e) {
					log.info("拷贝文件["+src+"]时发生异常!",e);
				}
			}
			log.info("copy "+hm.size()+" files!");
		} catch (FileNotFoundException e) {
			log.error("文件["+updateTxtPath+"]不存在！",e);
		} catch (IOException e) {
			log.error("文件["+updateTxtPath+"]读取失败！",e);
		}
	}

	/** 获得文件要拷贝到的目标路径，如果无需拷贝，则返回null */
	private String getDistPath(String path) {
		path = path.replace("\\", "/");
		if(path.indexOf(svnWebappUri)>=0){//使用Commit monitor生成的日志中
			path = path.substring(path.indexOf(svnWebappUri)+svnWebappUri.length());
		}
		String[] srcs = webSrcDirs.split(",");//所有要编译的目录
		if(path.startsWith(webroot+"/")){//在webroot目录下的文件
			return toDir + path.substring(webroot.length()+1);
		}
		for(int i=0;i<srcs.length;i++){
			if(srcs[i].trim().length()==0)//如果为空，不处理
				continue;
			if(path.startsWith(srcs[i]+"/")){//如果在编译的目录下，直接拷贝至WEB-INF/classes目录下
				return toDir+"WEB-INF/classes"+path.substring(srcs[i].length());
			}
		}
		return null;
	}

	/** 获得文件在本地的磁盘路径 */
	public String getWebPath(String path){
		String p = null;
		path = path.replace("\\", "/");
		if(path.indexOf(svnWebappUri)>=0){//使用Commit monitor生成的日志中
			path = path.substring(path.indexOf(svnWebappUri)+svnWebappUri.length());
		}
		p = webBase + path;
		return p;
	}
	
	private void copyFile(String src,String dist) throws IOException{
    	File f1 = new File(src);
    	File f2 = new File(dist);
    	if(!f1.exists()){
    		throw new IOException("file["+src+"]not found!");
    	}
    	if(!f1.isFile()){
    		throw new IOException("file["+src+"]is not a file!");
    	}
    	File p2 = new File(f2.getAbsolutePath()).getParentFile();
    	if(!p2.exists())//如果目标目录不存在，则创建之
    		p2.mkdirs();
    	BufferedInputStream in = null;
    	BufferedOutputStream out = null;
    	try {
			in = new BufferedInputStream(new FileInputStream(f1));
			out = new BufferedOutputStream(new FileOutputStream(f2));
			byte[] buff = new byte[10240];
			int len = in.read(buff);
			while(len>0){
				out.write(buff,0,len);
				len = in.read(buff);
			}
		} catch (IOException e) {
			throw e;
		}
		finally{
			try {
				if(in!=null)
					in.close();
			} catch (IOException e) {
				throw e;
			}
			if(out!=null)
				out.close();
		}
    	
    }

    private String blank10 = "          ";
    private String addEnds(String arg,int len){
    	if(arg==null)arg = "";
    	StringBuilder sb = new StringBuilder(arg+" ");
    	len -= sb.length();
    	if(len>0){
    		while(len>10){
    			sb.append(blank10);len-=10;
    		}
    		sb.append(blank10.substring(0,len));
    	}
    	return sb.toString();
    }
	public void setToDir(String toDir) {
		this.toDir = toDir;
		this.toDir = this.toDir.replace("\\", "/");
		if(!this.toDir.endsWith("/"))
			this.toDir+="/";
	}

	public void setUpdateTxtPath(String updateTxtPath) {
		this.updateTxtPath = updateTxtPath;
	}

	public void setWebroot(String webroot) {
		this.webroot = webroot;
	}

	public void setWebBase(String webBase) {
		this.webBase = webBase==null?"":webBase.replace("\\", "/");
		if(!this.webBase.endsWith("/"))
			this.webBase+="/";
	}

	public void setWebSrcDirs(String webSrcDirs) {
		this.webSrcDirs = webSrcDirs==null?"src":webSrcDirs;
	}

	public void setSvnWebappUri(String svnWebappUri) {
		this.svnWebappUri = svnWebappUri;
	}

}
